﻿namespace MovieTicket.WebApi.Handlers
{
    using System;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web;

    using MovieTicket.WebApi.Common;

    /// <summary>
    ///     Class AuthMessageHandler
    /// </summary>
    public class AuthMessageHandler : DelegatingHandler
    {
        #region Fields

        private string _userName;

        #endregion

        #region Methods

        /// <summary>
        /// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation.
        /// </summary>
        /// <param name="request">The HTTP request message to send to the server.</param>
        /// <param name="cancellationToken">A cancellation token to cancel operation.</param>
        /// <returns>Returns <see cref="T:System.Threading.Tasks.Task`1" />. The task object representing the asynchronous operation.</returns>
        protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, 
            CancellationToken cancellationToken)
        {
            // if the credentials are validated,
            // set CurrentPrincipal and Current.User
            if (ValidateCredentials(request.Headers.Authorization))
            {
                Thread.CurrentPrincipal = new MovieTicketsPrincipal(_userName);
                HttpContext.Current.User = new MovieTicketsPrincipal(_userName);
            }

            // Execute base.SendAsync to execute default
            // actions and once it is completed, 
            // capture the response object and add 
            // WWW-Authenticate header if the request 
            // was marked as unauthorized.
            return base.SendAsync(request, cancellationToken).ContinueWith(
                task =>
                    {
                        HttpResponseMessage response = task.Result;
                        if (response.StatusCode == HttpStatusCode.Unauthorized
                            && !response.Headers.Contains("WWW-Authenticate"))
                        {
                            response.Headers.Add("WWW-Authenticate", "Basic");
                        }

                        return response;
                    },
                cancellationToken);
        }

        // Method to validate credentials from Authorization
        // header value
        private bool ValidateCredentials(AuthenticationHeaderValue authenticationHeaderVal)
        {
            if (authenticationHeaderVal != null && !string.IsNullOrEmpty(authenticationHeaderVal.Parameter))
            {
                string[] decodedCredentials =
                    Encoding.ASCII.GetString(Convert.FromBase64String(authenticationHeaderVal.Parameter))
                        .Split(new[] { ':' });

                // now decodedCredentials[0] will contain 
                // username and decodedCredentials[1] will                  
                // contain password.You need to implement your own
                // business logic to verify credentials here.
                // For simplicity, we are hardcoding username 
                // and password here.
                string decodedUserName = decodedCredentials[0], decodedPassword = decodedCredentials[1];
                if ((decodedUserName.Equals("username") || decodedUserName.Equals("username1") || decodedUserName.Equals("defor")) && (decodedPassword.Equals("password") || decodedPassword.Equals("password1") || decodedPassword.Equals("xxx")))
                {
                    _userName = decodedUserName;
                    return true; // request authenticated.
                }
            }

            return false; // request not authenticated.
        }

        #endregion
    }
}